#include "robotdialog.h"
#include "MessageBox.h"
#include "models/operatelogmodel.h"
#include "ui_robotdialog.h"

#include <models/robotlist.h>

#include <QHBoxLayout>
#include <QScrollBar>
#include <QScroller>
#include <QScrollerProperties>
#include <mainwindow.h>


RobotDialog::RobotDialog(Robot *pRobot, QWidget *parent):
    PopupDialog(parent),
    ui(new Ui::RobotDialog),
    m_pRobot(pRobot)
{
    ui->setupUi(this);

    // 设置视频表格的样式
    ui->video_table->setStyleSheet(
        "QTableView {"
        "    background-color: #232426;"
        "    border: 1px solid #48494E;"
        "    color: white;"
        "    gridline-color: #48494E;"
        "}"
        );

    // 单独设置表头样式
    QString headerStyle = QString(
                              "QHeaderView {"
                              "    border: none;"
                              "}"
                              "QHeaderView::section {"
                              "    height: %1px;"
                              "    background-color: #232426;"
                              "    color: lightgray;"
                              "    font: %2px '微软雅黑';"
                              "    border: none;"
                              "    border-bottom: 1px solid #48494E;"
                              "    border-right: 1px solid #48494E;"
                              "    padding-left: 5px;"
                              "}"
                              "QHeaderView::section:last {"
                              "    border-right: none;"
                              "}").arg(int(50*g_yScale)).arg(int(20*g_xScale));
    ui->video_table->horizontalHeader()->setStyleSheet(headerStyle);
    // 显示网格线
    ui->video_table->setShowGrid(true);
    ui->video_table->setGridStyle(Qt::SolidLine);

    // 创建数据模型
    m_videoModel = new QStandardItemModel(this);
    m_videoModel->setColumnCount(3);
    m_videoModel->setHorizontalHeaderLabels(QStringList() << "名称" << "地址" << "操作");

    // 设置模型
    ui->video_table->setModel(m_videoModel);

    // 设置表头属性
    ui->video_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    ui->video_table->horizontalHeader()->setSectionsClickable(false);   // 禁用表头点击
    ui->video_table->horizontalHeader()->setFixedHeight(int(50*g_yScale));           // 固定表头高度

    // 设置列宽
    ui->video_table->setColumnWidth(0, int(150*g_xScale));  // 名称列
    ui->video_table->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);  // 地址列
    ui->video_table->setColumnWidth(2, int(100*g_xScale));  // 操作列

    // 设置行高
    ui->video_table->verticalHeader()->hide();
    ui->video_table->verticalHeader()->setDefaultSectionSize(int(50*g_yScale));      // 设置默认行高
    ui->video_table->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); // 固定行高


    // 禁用水平滚动
    ui->video_table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->video_table->setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);

    // 设置垂直滚动
    ui->video_table->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
    ui->video_table->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    // 配置触摸滚动
    QScroller::grabGesture(ui->video_table, QScroller::TouchGesture);
    QScroller::grabGesture(ui->video_table, QScroller::LeftMouseButtonGesture);
    QScroller *scroller = QScroller::scroller(ui->video_table);
    QScrollerProperties properties = scroller->scrollerProperties();

    // 禁用水平和垂直方向的过度滚动
    properties.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
    properties.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);

    // 设置水平方向的拖动距离为0，实际上禁用了水平滚动
    properties.setScrollMetric(QScrollerProperties::DragStartDistance, 0.0);

    scroller->setScrollerProperties(properties);

    // 设置表格样式，禁用选中效果
    ui->video_table->setSelectionMode(QAbstractItemView::NoSelection);
    ui->video_table->setFocusPolicy(Qt::NoFocus);

    ui->left_tool->addItem("空");
    ui->left_tool->addItem("灵巧手");
    ui->left_tool->addItem("夹爪");
    ui->left_tool->addItem("吸盘");

    ui->right_tool->addItem("空");
    ui->right_tool->addItem("灵巧手");
    ui->right_tool->addItem("夹爪");
    ui->right_tool->addItem("吸盘");

    ui->head_type->addItem("普通头");
    ui->head_type->addItem("哨兵头");
    ui->head_type->addItem("感知头");

    ui->title_lab->setText(pRobot== NULL?tr("新建机器人"):tr("编辑机器人"));
    setModal(true);
    scaleWidgets(this,g_xScale,g_yScale);
    if(m_pRobot)
    {
        ui->name_edit->setValidator(new QRegExpValidator(QRegExp("[\u4e00-\u9fa5a-zA-Z0-9]+"), this));
        ui->name_edit->setText(m_pRobot->strName());
        ui->urdf_name->setText(m_pRobot->urdfName());
        ui->sport_ip->setText(m_pRobot->strSportIP());
        ui->sport_ip->setValidator(new QRegExpValidator(QRegExp("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$"), this));
        ui->sport_port->setText(m_pRobot->nSportPort()>0?QString("%1").arg(m_pRobot->nSportPort()):"");
        ui->sport_port->setValidator(new QIntValidator(1, 65535, this));
        ui->perception_ip->setText(m_pRobot->strPerceptionIP());
        ui->perception_ip->setValidator(new QRegExpValidator(QRegExp("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$"), this));
        ui->perception_port->setText(m_pRobot->nPerceptionrPort()>0?QString("%1").arg(m_pRobot->nPerceptionrPort()):"");
        ui->perception_port->setValidator(new QIntValidator(1, 65535, this));
        ui->slam_ip->setText(m_pRobot->strSlamIP());
        ui->slam_ip->setValidator(new QRegExpValidator(QRegExp("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$"), this));
        ui->slam_port->setText(m_pRobot->nSlamPort()>0?QString("%1").arg(m_pRobot->nSlamPort()):"");
        ui->slam_port->setValidator(new QIntValidator(1, 65535, this));
        ui->speak_ip->setText(m_pRobot->strSpeakIP());
        ui->speak_ip->setValidator(new QRegExpValidator(QRegExp("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$"), this));
        ui->speak_port->setText(m_pRobot->nSpeakPort()>0?QString("%1").arg(m_pRobot->nSpeakPort()):"");
        ui->speak_port->setValidator(new QIntValidator(1, 65535, this));
        ui->zero_ip->setText(m_pRobot->strZeroIP());
        ui->zero_ip->setValidator(new QRegExpValidator(QRegExp("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$"), this));
        ui->zero_port->setText(m_pRobot->nZeroPort()>0?QString("%1").arg(m_pRobot->nZeroPort()):"");
        ui->zero_port->setValidator(new QIntValidator(1, 65535, this));
        ui->telemetry_ip->setText(m_pRobot->strTelemetryIP());
        ui->telemetry_ip->setValidator(new QRegExpValidator(QRegExp("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$"), this));
        ui->telemetry_port->setText(m_pRobot->nTelemetryPort()>0?QString("%1").arg(m_pRobot->nTelemetryPort()):"");
        ui->telemetry_port->setValidator(new QIntValidator(1, 65535, this));
        ui->left_tool->setCurrentIndex((int)m_pRobot->leftTool());
        ui->right_tool->setCurrentIndex((int)m_pRobot->rightTool());
        ui->head_type->setCurrentIndex((int)m_pRobot->headType());
        ui->user_edit->setText(m_pRobot->strUser());
        ui->password_edit->setText(m_pRobot->strPassword());
        QList<VideoInfo>lsVideo = m_pRobot->lsVideo();
        for(auto it = lsVideo.begin(); it != lsVideo.end(); ++it)
        {
            addVideoRow(it->strName,it->strUrl);
        }
    }
}


void RobotDialog::scaleWidgets(QWidget *widget, double xScale,double yScale)
{
    setFixedSize(int(widget->width() * xScale), int(widget->height() * yScale));
    for (QWidget *child : widget->findChildren<QWidget*>()) {
        QRect geom = child->geometry();
        if (qobject_cast<QScrollBar*>(child))
            child->setFixedWidth(int(geom.width() * xScale));
        else if( qobject_cast<QLabel*>(child) ||
                 qobject_cast<TouchButton*>(child) ||
                 qobject_cast<QComboBox*>(child) ||
                 qobject_cast<QLineEdit*>(child)||
                 qobject_cast<QTableView*>(child))
        {
            int width = qMax(1, static_cast<int>(int(geom.width() * xScale)));
            //当按钮高度比较大时使用y方向比例，当按钮比较小时使用x比例，防止按钮被压扁
            int height = qMax(1, static_cast<int>((geom.height() == geom.width() ? int(geom.height() * xScale) : int(geom.height() * yScale))));
            child->setFixedSize(width,height);
            child->move(int(geom.left() * xScale),int(geom.top() * yScale));
            QFont font = child->font();
            if(font.pixelSize()> 0)
                font.setPixelSize(int(font.pixelSize()*xScale));
            else if(font.pointSize()> 0)
                font.setPixelSize(int(font.pointSize()*xScale));
            child->setFont(font);
        }
    }
}
RobotDialog::~RobotDialog()
{
    delete ui;
}

void RobotDialog::on_close_btn_clicked()
{
    reject();
}


void RobotDialog::on_pushButton_clicked()
{
    addVideoRow();
}

void RobotDialog::addVideoRow(const QString &name, const QString &url)
{
    int row = m_videoModel->rowCount();
    m_videoModel->insertRow(row);

    // 创建名称编辑框
    QLineEdit* nameEdit = new QLineEdit(ui->video_table);
    nameEdit->setValidator(new QRegExpValidator(QRegExp("[\u4e00-\u9fa5a-zA-Z0-9]+"), this));
    nameEdit->setText(name);
    QString strEditStyle =         QString(
                               "QLineEdit {"
                               "    background-color: transparent;"
                               "    border: 0px;"
                               "    padding: 5px;"
                               "    color: lightgray;"
                               "    font: %1px '微软雅黑';"
                               "}"
                               "QLineEdit:focus {"
                               "    border: 1px solid #00A4FF;"
                               "}").arg(int(18*g_xScale));
    nameEdit->setStyleSheet(strEditStyle);

    // 创建地址编辑框
    QLineEdit* urlEdit = new QLineEdit(ui->video_table);
    urlEdit->setText(url);
    urlEdit->setStyleSheet(strEditStyle);

    // 创建操作按钮容器
    QWidget* buttonWidget = new QWidget(ui->video_table);
    QHBoxLayout* buttonLayout = new QHBoxLayout(buttonWidget);
    buttonLayout->setMargin(0);

    // 创建删除按钮
    TouchButton* deleteBtn = new TouchButton("刪除",buttonWidget);
    deleteBtn->setFixedSize(int(60*g_xScale), int(40*g_xScale));
    //deleteBtn->setCursor(Qt::PointingHandCursor);
    deleteBtn->setStyleSheet(QString("QPushButton{\
                            background:transparent; \
                            color:#007BFF;\
                            font:%1px \"微软雅黑\"; \
                            border-color: #098CFF;\
                            border-width:1px;}\
                            QPushButton:pressed{ \
                            color:#0056b3; \
                            } \
                            QPushButton:disabled { \
                            color: gray; \
                            }").arg(int(18*g_xScale)));

    // 添加按钮到布局
    buttonLayout->addStretch();
    buttonLayout->addWidget(deleteBtn);
    buttonLayout->addStretch();

    // 设置单元格内容
    ui->video_table->setIndexWidget(m_videoModel->index(row, 0), nameEdit);
    ui->video_table->setIndexWidget(m_videoModel->index(row, 1), urlEdit);
    ui->video_table->setIndexWidget(m_videoModel->index(row, 2), buttonWidget);

    // 连接删除按钮信号
    connect(deleteBtn, &QPushButton::clicked, this, [=]() {
        QString strName = nameEdit->text().trimmed();
        if(strName.length()== 0 || question(MainWindow::getInstance(),tr("确定要删除视频流\"%1\"？").arg(strName))==0)
            {
            m_videoModel->removeRow(ui->video_table->indexAt(buttonWidget->pos()).row());
            ui->pushButton->setFocus();
        }
    });
}


void RobotDialog::on_ok_btn_clicked()
{
    ui->err_lab->setText("");
    //保存数据
    QString strName = ui->name_edit->text().trimmed();
    QString strUrdfName=ui->urdf_name->text().trimmed();
    if(strName.isEmpty())
    {
        ui->err_lab->setText(tr("机器人名称不能为空"));
        return;
    }
    QString strSportIP= ui->sport_ip->text().trimmed();
    int nSportPort = ui->sport_port->text().toInt();
    QRegExp ipRegex("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$");
    if(!ipRegex.exactMatch(strSportIP))
    {
        ui->err_lab->setText(tr("请正确输入运控IP地址"));
        return;
    }
    if(nSportPort <= 0 || nSportPort > 65535)
    {
        ui->err_lab->setText(tr("请输入正确的运控端口号(1-65535)"));
        return;
    }

    QString strPerceptionIP = ui->perception_ip->text().trimmed();
    int nPerceptionrPort = ui->perception_port->text().toInt();
    if(strPerceptionIP.length() > 0 )
    {
        if(!ipRegex.exactMatch(strPerceptionIP))
        {
        ui->err_lab->setText(tr("感知IP格式错误"));
        return;
        }
        if(nPerceptionrPort <= 0 || nPerceptionrPort > 65535)
        {
            ui->err_lab->setText(tr("请输入正确的感知端口号(1-65535)"));
            return;
        }
    }

    QString strSlamIP = ui->slam_ip->text().trimmed();
    int nSlamPort = ui->slam_port->text().toInt();
    if(strSlamIP.length() > 0 )
    {
        if(!ipRegex.exactMatch(strSlamIP))
        {
            ui->err_lab->setText(tr("Slam IP格式错误"));
            return;
        }
        if(nSlamPort <= 0 || nSlamPort > 65535)
        {
            ui->err_lab->setText(tr("请输入正确的slam端口号(1-65535)"));
            return;
        }
    }

    QString strSpeakIP = ui->speak_ip->text().trimmed();
    int nSpeakPort = ui->speak_port->text().toInt();
    if(strSpeakIP.length() > 0 )
    {
        if(!ipRegex.exactMatch(strSpeakIP))
        {
            ui->err_lab->setText(tr("喊话IP格式错误"));
            return;
        }
        if(nSpeakPort <= 0 || nSpeakPort > 65535)
        {
            ui->err_lab->setText(tr("请输入正确的喊话端口号(1-65535)"));
            return;
        }
    }

    QString strZeroIP = ui->zero_ip->text().trimmed();
    int nZeroPort = ui->zero_port->text().toInt();
    if(strZeroIP.length() > 0 )
    {
        if(!ipRegex.exactMatch(strZeroIP))
        {
            ui->err_lab->setText(tr("标零IP格式错误"));
            return;
        }
        if(nZeroPort <= 0 || nZeroPort > 65535)
        {
            ui->err_lab->setText(tr("请输入正确的标零端口号(1-65535)"));
            return;
        }
    }

    QString strTelemetryIP = ui->telemetry_ip->text().trimmed();
    int nTelemetryPort = ui->telemetry_port->text().toInt();
    if(strTelemetryIP.length() > 0 )
    {
        if(!ipRegex.exactMatch(strTelemetryIP))
        {
            ui->err_lab->setText(tr("数采IP格式错误"));
            return;
        }
        if(nTelemetryPort <= 0 || nTelemetryPort > 65535)
        {
            ui->err_lab->setText(tr("请输入正确的数采端口号(1-65535)"));
            return;
        }
    }
    QList<VideoInfo> lsVideo;

    // 从表格中获取视频数据
    for(int row = 0; row < m_videoModel->rowCount(); row++) {
        QLineEdit* nameEdit = qobject_cast<QLineEdit*>(ui->video_table->indexWidget(m_videoModel->index(row, 0)));
        QLineEdit* urlEdit = qobject_cast<QLineEdit*>(ui->video_table->indexWidget(m_videoModel->index(row, 1)));

        if(nameEdit && urlEdit) {
            QString name = nameEdit->text().trimmed();
            QString url = urlEdit->text().trimmed();
            // 验证数据
            if(name.isEmpty()) {
                ui->err_lab->setText(tr("视频名称不能为空"));
                return;
            }
            if(url.isEmpty()) {
                ui->err_lab->setText(tr("视频地址不能为空"));
                return;
            }
            // 检查名称是否重复
            // if(mpVideo.contains(name)) {
            //     ui->err_lab->setText(tr("视频名称不能重复"));
            //     return;
            // }
            for(int i = 0; i < lsVideo.size(); ++i)
            {
                if(lsVideo[i].strName == name)
                {
                    ui->err_lab->setText(tr("视频名称不能重复"));
                    return;
                }
                else if(lsVideo[i].strUrl == url)
                {
                    ui->err_lab->setText(tr("视频地址不能重复"));
                    return;
                }
            }
            lsVideo.push_back(VideoInfo{name,url});
        }
    }

    // 至少需要一个视频配置
    // if(lsVideo.isEmpty()) {
    //     ui->err_lab->setText(tr("请至少添加一个视频配置"));
    //     return;
    // }

    QString strErr = "";
    bool bSuccess = false;
    if(m_pRobot)
    {
        bSuccess = RobotList::getInstance()->updateRobot(m_pRobot->nID(),strName,strUrdfName,
                                                         strSportIP,
                                                         nSportPort,
                                                         strPerceptionIP,
                                                         nPerceptionrPort,
                                                         strSlamIP,
                                                         nSlamPort,
                                                         strSpeakIP,
                                                         nSpeakPort,
                                                         strZeroIP,
                                                         nZeroPort,
                                                         strTelemetryIP,
                                                         nTelemetryPort,
                                                          ui->left_tool->currentIndex(),ui->right_tool->currentIndex(),ui->head_type->currentIndex(), ui->user_edit->text(),ui->password_edit->text(),lsVideo, strErr);
        OPERATE_LOG("修改机器人："+strName);
    }
    else
    {
        bSuccess = RobotList::getInstance()->addRobot(strName,strUrdfName,
                                                      strSportIP,
                                                      nSportPort,
                                                      strPerceptionIP,
                                                      nPerceptionrPort,
                                                      strSlamIP,
                                                      nSlamPort,
                                                      strSpeakIP,
                                                      nSpeakPort,
                                                      strZeroIP,
                                                      nZeroPort,
                                                      strTelemetryIP,
                                                      nTelemetryPort, ui->left_tool->currentIndex(),ui->right_tool->currentIndex(),ui->head_type->currentIndex(),
                                                      ui->user_edit->text(),ui->password_edit->text(),lsVideo, strErr);
        OPERATE_LOG("新建机器人："+strName);
    }

    if(bSuccess) {
        accept();
    } else {
        ui->err_lab->setText(strErr);
        reject();
    }
}


void RobotDialog::on_cancel_ban_clicked()
{
    reject();
}

